//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.Text.RegularExpressions;


namespace CommunityServer.Components
{
	#region TextPart
	/// <summary>
	/// A tokenized object which allows pieces of text to be replaced 
	/// for more meaningful content
	/// </summary>
	public class TextPart : IEnumerable
	{
		#region Private Members
		private string _part;
		private string[] _parameters;
		#endregion

		#region .cnstr
		internal TextPart(string part)
		{
			if(part == null)
			{
				throw new ArgumentNullException("Part", "The parameter part can not be null");
			}

			if(part.Length < 3)
				throw new ArgumentOutOfRangeException("Part", "The parameter part must be at least 3 characters long");
		
			_part = part;
			_parameters = part.Substring(1,part.Length-2).Split(':');
		}
		#endregion

		#region Properties
		/// <summary>
		/// The raw part/pattern
		/// </summary>
		public string Part
		{
			get{ return _part;}
		}

		/// <summary>
		/// Number of paramters
		/// </summary>
		public int Count
		{
			get { return _parameters.Length;}
		}

		/// <summary>
		/// returns the first parameter which usually defines
		/// the action
		/// </summary>
		public string Name
		{
			get{return Get(0);}
		}

		/// <summary>
		/// returns the second paramter. This item may not exist
		/// </summary>
		public string Value
		{
			get { return Get(1);}
		}

		#endregion

		#region Direct Access

		/// <summary>
		/// returns the paramter at the current index. Same as calling .Get
		/// </summary>
		public string this[int index]
		{
			get
			{
				return Get(index);
			}
		}

		/// <summary>
		/// return the parameter at the current index.
		/// </summary>
		/// <param name="index"></param>
		/// <returns></returns>
		public virtual string Get(int index)
		{
			if(index >= Count)
				throw new ArgumentOutOfRangeException("The requested index value does not exist");

			if(index < 0)
				throw new ArgumentOutOfRangeException("Index value must be zero or greater");

			return _parameters[index];
		}

		/// <summary>
		/// Attempts to convert the parameter to a boolean
		/// </summary>
		/// <param name="index"></param>
		/// <returns></returns>
		public bool ConvertToBoolean(int index)
		{
            try
            {
                return Boolean.Parse(Get(index));
            }
            catch
            {
                return false;
            }
		}

		/// <summary>
		/// Attempts to convert the parameter to an integer
		/// </summary>
		/// <param name="index"></param>
		/// <returns></returns>
		public int ConvertToInt(int index)
		{
            try
            {
                return Int32.Parse(Get(index));
            }
            catch
            {
                return 0;
            }
		}

		#endregion

		#region IEnumerable Members

		public IEnumerator GetEnumerator()
		{
			return _parameters.GetEnumerator();
		}

		#endregion

		#region methods
		/// <summary>
		/// Performs a find and replace on the token
		/// </summary>
		/// <param name="oldText">Text to search</param>
		/// <param name="newValue">To to replace</param>
		/// <returns>oldText reformatted</returns>
		public string Replace(string oldText, string newValue)
		{
			return Regex.Replace(oldText, "\\[" + string.Join(":",this._parameters) + "\\]",newValue, RegexOptions.IgnoreCase);
		}
		#endregion
	}

	#endregion

	#region Collection
	/// <summary>
	/// Contains a collection of TextParts
	/// </summary>
	public class TextPartSet : IEnumerable
	{
		/// <summary>
		/// Internal Collection
		/// </summary>
		ArrayList list = null;

		/// <summary>
		/// intneral scope.
		/// </summary>
		internal TextPartSet(int count)
		{
			list = new ArrayList(count);
		}

		/// <summary>
		/// Adds a new TextPart
		/// </summary>
		/// <param name="part"></param>
		internal void Add(TextPart part)
		{
			list.Add(part);
		}

		/// <summary>
		/// Number of TextParts
		/// </summary>
		public int Count
		{
			get{ return list.Count;}
		}

		public TextPart this[int index]
		{
			get
			{
				return Get(index);
			}
		}

		public TextPart Get(int index)
		{
			 return list[index] as TextPart;
		}

		#region IEnumerable Members

		public IEnumerator GetEnumerator()
		{
			return list.GetEnumerator();
		}

		#endregion
	}
	#endregion

	#region TextPartManager
	/// <summary>
	/// Manages the creation of TextParts and TextPartSets
	/// </summary>
	public class TextPartManager
	{
		//We can re-use this regex
		private static readonly Regex regex = new Regex("\\[[a-zA-Z0-9:_.\\$\\-\\+\\!\\*\\\'\\(\\)\\%\\&\\,\\/\\;\\=\\?\\@\\s]+\\]",RegexOptions.IgnoreCase|RegexOptions.Compiled);

		private TextPartManager(){}

		/// <summary>
		/// Creates a TextPart based on a raw string. This will fail if not formatted correctly
		/// </summary>
		/// <param name="part">raw text</param>
		/// <returns>A TextPart based on the string</returns>
		public static TextPart CreatePart(string part)
		{
			return new TextPart(part);
		}

		/// <summary>
		/// Parses a raw block of text and extracts a collection of TextParts
		/// </summary>
		/// <param name="text">raw text to parse</param>
		/// <returns>A collection of parts based on the text</returns>
		public static TextPartSet Parse(string text)
		{
			MatchCollection mc = regex.Matches(text);
			TextPartSet tps = new TextPartSet(mc.Count);
			foreach(Match m in mc)
			{
				tps.Add(CreatePart(m.ToString()));
			}

			return tps;
		}
	}
	#endregion
}
